package com.kellycheung.chicken_go_go;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import com.kellycheung.chicken_go_go.GameScene.GameSceneStatus;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;

public class GameObject extends BaseObject {
	public class GOAnimation {
		protected GameObject go;
		protected int[] iImgResId;
		protected Matrix mRotator;
		
		protected ArrayList<Bitmap> albImgBmp;
		
		protected int iImgResCur;
		protected int iFPS;
		protected boolean bIsPlayAni;
		protected int iPlayFrameCnt;
		protected int iPlayFrameTtl;
		
		public GOAnimation( GameObject p_go , int[] p_iResId , int p_iFPS , Matrix p_mRotator ) {
			try {
				Bitmap b;
				
				this.go = p_go;
				this.iImgResId = p_iResId;
				this.iImgResCur = 0;
				this.mRotator = p_mRotator;
				this.iPlayFrameCnt = 0;
				this.iPlayFrameTtl = 0;
				
				this.albImgBmp = new ArrayList<Bitmap>();
				for ( int i = 0 ; i < this.iImgResId.length ; i++ ) {
					if ( this.iImgResId[i] != 0 ) {
						b = BitmapFactory.decodeResource( this.go.gsScene.geMain.aApp.getResources(), this.iImgResId[i] );
					}
					else {
						b = null;
					}
					
					this.albImgBmp.add( b );
				}
				
				this.iFPS = p_iFPS;
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void destroy() {
			try {
				if ( this.albImgBmp != null ) {
					for ( Bitmap b : this.albImgBmp ) {
						if ( b != null ) {
							b.recycle();
						}
					}
					
					this.albImgBmp.clear();
					this.albImgBmp = null;
				}
				
				this.mRotator = null;
				this.iImgResId = null;
				this.go = null;
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.destroy" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void setFPS() {
			try {
				if ( this.iFPS != 0 ) {
					if ( this.go.tAniTimer == null ) {
						this.go.tAniTimer = new Timer();
					}
					else {
						this.go.tAniTimer.cancel();
						this.go.tAniTimer.purge();
						this.go.tAniTimer = new Timer();
					}
					
					this.go.tAniTimer.scheduleAtFixedRate( new TimerTask() {
						@Override
						public void run() {
							// TODO Auto-generated method stub
							if ( go.isAllowRun() ) {
								if ( bIsPlayAni || iImgResCur != 0 ) {
									iImgResCur = iImgResCur >= (albImgBmp.size()-1) ? 0 : iImgResCur + 1;
									iPlayFrameCnt++;
									iPlayFrameTtl++;
								}
							}
						}
					} , 0 , ( this.iFPS > 0 ? 1000/this.iFPS : ( this.go.gsScene.geMain.iDelay > 0 ? this.go.gsScene.geMain.iDelay : 1000 ) ) );
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.setFPS" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void scaleImageByWidth( float p_fW ) {
			try {
				this.scaleImage( p_fW , ( p_fW / this.getWidth() * this.getHeight() ) );
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.scaleImageByWidth" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void scaleImageByHeight( float p_fH ) {
			try {
				this.scaleImage( ( p_fH / this.getHeight() * this.getWidth() ) , p_fH );
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.scaleImageByHeight" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void scaleImageByRatio( float p_fRatio ) {
			try {
				this.scaleImage( (float)this.getWidth()*p_fRatio , (float)this.getHeight()*p_fRatio );
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.scaleImageByRatio" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void scaleImage( float p_fW , float p_fH ) {
			try {
				for ( Bitmap b : this.albImgBmp ) {
					if ( b != null ) {
						b = Bitmap.createScaledBitmap( b , Math.round(p_fW) , Math.round(p_fH) , true );
					}
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.scaleImage" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void setBound() {
			try {
				if ( this.albImgBmp.size() > 0 ) {
					this.go.grBound = new GRectangle( 0f , 0f , 0f , 0f );
				}
				
				this.go.grBound.set( new GRectangle( this.go.gcCoord , this.go.gcCoord.offset( this.getWidth() , this.getHeight() ) ).convCoord( GOAnchor.DownRight ).convCoord( this.go.goaAnchor ) );
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.scaleImage" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void draw( Canvas p_c , Paint p_p ) {
			try {
				if ( this.albImgBmp.size() > 0 ) {
					if ( this.albImgBmp.get(this.iImgResCur) != null ) {
						p_c.drawBitmap( this.albImgBmp.get(this.iImgResCur) , this.go.grBound.fLeft , this.go.grBound.fUp , p_p );
					}
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.draw" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void stop() {
			try {
				this.bIsPlayAni = false;
				this.iImgResCur = 0;
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.stop" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public void play() {
			try {
				this.setFPS();
				this.setBound();
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.play" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
		
		public float getWidth() {
			try {
				if ( this.albImgBmp.get(this.iImgResCur) != null ) {
					return (float)this.albImgBmp.get(this.iImgResCur).getWidth();
				}
				else if ( this.albImgBmp.get(0) != null ) {
					return (float)this.albImgBmp.get(0).getWidth();
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.getWidth" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return 0;
		}
		
		public float getHeight() {
			try {
				if ( this.albImgBmp.get(this.iImgResCur) != null ) {
					return (float)this.albImgBmp.get(this.iImgResCur).getHeight();
				}
				else if ( this.albImgBmp.get(0) != null ) {
					return (float)this.albImgBmp.get(0).getHeight();
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.getHeight" );
				GameUtil.ErrorHandler( this , p_e );
			}
			
			return 0;
		}
		
		public void setImgResCur( int p_iImgResCur ) {
			try {
				if ( p_iImgResCur < this.albImgBmp.size() ) {
					this.iImgResCur = p_iImgResCur; 
				}
	        } catch ( Exception p_e ) {
				// TODO Auto-generated catch block
				GameUtil.LogMsg( this , "GOAnimation.setImgResCur" );
				GameUtil.ErrorHandler( this , p_e );
			}
		}
	}
	
	protected ArrayList<GOAnimation> algoaAni;
	
	protected Timer tAniTimer;
	protected GRectangle grBound;
	
	protected int iAniIdx;
	
	public GameObject( GameScene p_gsScene , int p_iZOrder , GOAnchor p_goa ) {
		this( p_gsScene , p_iZOrder , p_goa , 0f , 0f );
	}
	
	public GameObject( GameScene p_gsScene , int p_iZOrder , GOAnchor p_goa , float p_fX , float p_fY ) {
		super( p_gsScene , p_iZOrder , p_goa , p_fX , p_fY );
	}
	
	@Override
	public void destroy() {
		try {
			if ( this.algoaAni != null ) {
				for ( GOAnimation goa : this.algoaAni ) {
					goa.destroy();
				}
				this.algoaAni.clear();
				this.algoaAni = null;
			}
			
			if ( this.tAniTimer != null ) {
				this.tAniTimer.cancel();
				this.tAniTimer.purge();
				this.tAniTimer = null;
			}
			
			this.grBound = null;
			
			super.destroy();
        } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.destroy" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public int addAnimation( int[] p_iResId ) {
		try {
			return this.addAnimation( p_iResId , 0 , null );
        } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.addAnimation(int[])" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public int addAnimation( int[] p_iResId , int p_iFPS ) {
		try {
			return this.addAnimation( p_iResId , p_iFPS , null );
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.addAnimation(int[],int)" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public int addAnimation( int[] p_iResId , Matrix p_mRotator ) {
		try {
			return this.addAnimation( p_iResId , 0 , p_mRotator );
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.addAnimation(int[],Matrix)" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public int addAnimation( int[] p_iResId , int p_iFPS , Matrix p_mRotator ) {
		try {
			if ( p_iResId != null ) {
				if ( this.algoaAni == null ) {
					this.algoaAni = new ArrayList<GOAnimation>();
					this.iAniIdx = 0;
				}
				
				this.algoaAni.add( new GOAnimation( this , p_iResId , p_iFPS , p_mRotator ) );
				
				if ( this.algoaAni.size() == 1 ) {
					this.setAnimation();
				}
				
				return this.algoaAni.size();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.addAnimation(int[],int,Matrix)" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public void setAnimation() {
		try {
			if ( this.algoaAni != null ) {
				this.setAnimation( 0 );
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setAnimation" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setAnimation( int p_iAniIdx ) {
		try {
			if ( this.algoaAni.size() >= (p_iAniIdx+1) ) {
				this.algoaAni.get( this.iAniIdx ).stop();
				this.iAniIdx = p_iAniIdx;
				this.algoaAni.get( this.iAniIdx ).play();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setAnimation(int)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public boolean isAnimationPlaying() {
		try {
			if ( this.algoaAni != null ) {
				return this.algoaAni.get( this.iAniIdx ).bIsPlayAni;
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.isAnimationPlaying" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public void playAnimation( boolean p_bPlayAni ) {
		try {
			if ( this.algoaAni != null ) {
				this.algoaAni.get( this.iAniIdx ).bIsPlayAni = p_bPlayAni;
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.playAnimation" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public boolean isAllowRun() {
		try {
			if ( this.gsScene != null ) {
				return GameSceneStatus.IsAllowRun( this.gssAllowStatus , this.gsScene.gssStatus );
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.isAllowRun" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public void setZOrder( int p_iZOrder ) {
		this.iZOrder = p_iZOrder;
	}
	
	public int getZOrder() {
		return this.iZOrder;
	}
	
	public void setCoord( GCoordinate p_gc ) {
		try {
			this.setCoord( p_gc.fX , p_gc.fY );
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setCoord(GCoordinate)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setCoord( float p_fX , float p_fY ) {
		try {
			this.gcCoord.set( p_fX , p_fY );
			this.setBound();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setCoord(float,float)" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void setBound() {
		try {
			if ( this.algoaAni != null ) {
				this.algoaAni.get( this.iAniIdx ).setBound();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setBound" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public float getWidth() {
		try {
			if ( this.algoaAni != null ) {
				return (float)this.algoaAni.get( this.iAniIdx ).getWidth();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.getWidth" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public float getHeight() {
		try {
			if ( this.algoaAni != null ) {
				return (float)this.algoaAni.get( this.iAniIdx ).getHeight();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.getHeight" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public void draw( Canvas p_c , Paint p_p ) {
		try {
			if ( this.algoaAni != null ) {
				if ( this.iAniIdx >= 0 && this.iAniIdx < this.algoaAni.size() ) {
					this.algoaAni.get( this.iAniIdx ).draw( p_c , p_p );
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.draw" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void preGameLoopLogic() {
		try {
			this.setBound();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.preGameLoopLogic" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void gameLoopLogic() {
	}
	
	public void postGameLoopLogic() {
	}
	
	public boolean isCollided( GameObject p_go ) {
		try {
			return this.isCollided( p_go.grBound );
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.isCollided(GameObject)" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public boolean isCollided( GRectangle p_gr ) {
		try {
			return this.grBound.isCollided( p_gr );
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.isCollided(GRectangle)" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return false;
	}
	
	public void setAniImgResCur( int p_iImgResCur ) {
		try {
			if ( this.algoaAni != null ) {
				if ( this.iAniIdx >= 0 && this.iAniIdx < this.algoaAni.size() ) {
					this.algoaAni.get( this.iAniIdx ).setImgResCur( p_iImgResCur );
				}
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.setAniImgResCur" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public int playLoopCnt() {
		try {
			GOAnimation goa = this.algoaAni.get( this.iAniIdx );
			
			if ( goa != null ) {
				return goa.iPlayFrameCnt / goa.albImgBmp.size();
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.playLoopCnt" );
			GameUtil.ErrorHandler( this , p_e );
		}
		
		return 0;
	}
	
	public void resetLoopCnt() {
		try {
			GOAnimation goa = this.algoaAni.get( this.iAniIdx );
			
			if ( goa != null ) {
				goa.iPlayFrameCnt = 0;
			}
	    } catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameObject.resetLoopCnt" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
}
